package edu.upc.fib.lamsandroid.server.lams.manager;

import edu.upc.fib.lamsandroid.server.api.model.Activity;
import edu.upc.fib.lamsandroid.server.api.model.Lesson;
import edu.upc.fib.lamsandroid.server.api.model.Organisation;
import edu.upc.fib.lamsandroid.server.api.model.ToolType;
import edu.upc.fib.lamsandroid.server.lams.mapper.*;
import edu.upc.fib.lamsandroid.server.lams.model.*;
import edu.upc.fib.lamsandroid.server.manager.LessonManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
public class LessonManagerImpl implements LessonManager {

    @Autowired
    private LamsLessonMapper lessonMapper;

    @Autowired
    private LamsLearningDesignMapper learningDesignMapper;

    @Autowired
    private LamsLearningActivityMapper learningActivityMapper;

    @Autowired
    private LamsLearningTransitionMapper learningTransitionMapper;

    @Autowired
    private LamsToolMapper toolMapper;


    @Override
    public List<Lesson> getByOrganisation(Organisation organisation) {

        LamsLessonExample lessonExample = new LamsLessonExample();
        lessonExample.createCriteria()
                .andOrganisationIdEqualTo(organisation.getExternalId())
                .andLessonStateIdNotEqualTo(7);

        ArrayList<Lesson> lessons = new ArrayList<Lesson>();
        List<LamsLesson> lamsLessons = lessonMapper.selectByExampleWithBLOBs(lessonExample);
        for (LamsLesson lamsLesson : lamsLessons) {
            Lesson lesson = new Lesson();
            lesson.setExternalId(lamsLesson.getLessonId());
            lesson.setTitle(lamsLesson.getName());
            lesson.setDescription(lamsLesson.getDescription());
            lessons.add(lesson);
        }

        return lessons;
    }

    @Override
    public Lesson fetchById(Long id) {
        // get lesson
        LamsLessonExample lessonExample = new LamsLessonExample();
        lessonExample.createCriteria().andLessonIdEqualTo(id);
        List<LamsLesson> lamsLessons = lessonMapper.selectByExampleWithBLOBs(lessonExample);
        if(lamsLessons.size() > 0) {
            LamsLesson lamsLesson = lamsLessons.get(0);

            // get design
            LamsLearningDesignExample learningDesignExample = new LamsLearningDesignExample();
            learningDesignExample.createCriteria().andLearningDesignIdEqualTo(lamsLesson.getLearningDesignId());
            List<LamsLearningDesign> learningDesigns = learningDesignMapper.selectByExample(learningDesignExample);
            if(learningDesigns.size() > 0) {
                LamsLearningDesign learningDesign = learningDesigns.get(0);

                // get activities
                LamsLearningActivityExample learningActivityExample = new LamsLearningActivityExample();
                learningActivityExample.createCriteria().andLearningDesignIdEqualTo(learningDesign.getLearningDesignId());
                List<LamsLearningActivityWithBLOBs> learningActivities = learningActivityMapper.selectByExampleWithBLOBs(learningActivityExample);
                System.out.println("Got "+learningActivities.size()+" activities");

                // transitions
                LamsLearningTransitionExample learningTransitionExample = new LamsLearningTransitionExample();
                learningTransitionExample.createCriteria().andLearningDesignIdEqualTo(learningDesign.getLearningDesignId());
                List<LamsLearningTransition> learningTransitions = learningTransitionMapper.selectByExample(learningTransitionExample);
                System.out.println("Got "+learningTransitions.size()+" transitions");

                // and create and set ordered activity list (sequence)
                Lesson lesson = new Lesson();
                lesson.setExternalId(lamsLesson.getLessonId());
                lesson.setTitle(lamsLesson.getName());
                lesson.setDescription(lamsLesson.getDescription());
                addOrderedActivities(lesson, learningDesign, learningActivities, learningTransitions);
                return lesson;
            }
        }

        return null;
    }

    @Override
    public List<Lesson> fetchAll() {
        return null;  //To change body of implemented methods use File | Settings | File Templates.
    }

    private void addOrderedActivities(Lesson lesson, LamsLearningDesign learningDesign, List<LamsLearningActivityWithBLOBs> activities, List<LamsLearningTransition> transitions) {
        ArrayList<Activity> orderedActivities = new ArrayList<Activity>(activities.size());

        LamsLearningActivityExample learningActivityExample = new LamsLearningActivityExample();
        learningActivityExample.createCriteria().andActivityIdEqualTo(learningDesign.getFirstActivityId());
        List<LamsLearningActivityWithBLOBs> learningActivities = learningActivityMapper.selectByExampleWithBLOBs(learningActivityExample);

        if(learningActivities.size() > 0) {
            orderedActivities.add(buildActivity(learningActivities.get(0)));

            LamsLearningActivityWithBLOBs next = getNextActivity(learningActivities.get(0), activities, transitions);
            while(next != null) {
                orderedActivities.add(buildActivity(next));
                next = getNextActivity(next, activities, transitions);
            }
        } else {
            System.out.println("First activity not found!");
        }

        lesson.setActivities(orderedActivities);
    }
    private LamsLearningActivityWithBLOBs getNextActivity(LamsLearningActivityWithBLOBs activity, List<LamsLearningActivityWithBLOBs> activities, List<LamsLearningTransition> transitions) {
        for(LamsLearningTransition transition : transitions) {
            if(transition.getFromActivityId().equals(activity.getActivityId())) {
                for(LamsLearningActivityWithBLOBs nextActivity : activities) {
                    if(transition.getToActivityId().equals(nextActivity.getActivityId())) {
                        return nextActivity;
                    }
                }
            }
        }

        return null;
    }

    private Activity buildActivity(LamsLearningActivityWithBLOBs lamsActivity) {
        ToolType toolType = new ToolType();
        toolType.setExternalId(-1L);
        toolType.setName("unknown");
        toolType.setDescription("unknown tool, check logs");

        if(lamsActivity.getToolId() != null) {
            LamsToolExample toolExample = new LamsToolExample();
            toolExample.createCriteria().andToolIdEqualTo(lamsActivity.getToolId());
            List<LamsToolWithBLOBs> tools = toolMapper.selectByExampleWithBLOBs(toolExample);
            if(tools.size() > 0) {
                toolType.setExternalId(tools.get(0).getToolId());
                toolType.setName(tools.get(0).getToolDisplayName());
                toolType.setDescription(tools.get(0).getDescription());
            } else {
                System.out.println("Unknown TOOL!!");
            }
        } else {
            System.out.println("Activity without TOOL ASSOCIATED!!");
        }

        Activity activity = new Activity();
        activity.setToolType(toolType);
        activity.setExternalId(lamsActivity.getActivityId());
        activity.setCategoryId(lamsActivity.getActivityCategoryId());
        activity.setTypeId(lamsActivity.getLearningActivityTypeId());
        activity.setTitle(lamsActivity.getTitle());
        activity.setDescription(lamsActivity.getDescription());
        activity.setHelpText(lamsActivity.getHelpText());
        activity.setUiImage(lamsActivity.getLibraryActivityUiImage());

        return activity;
    }
}
